#include "NonMartiale.h"

#include "lib.h"

#include "Caracteristique.h"

#include <boost/assign/list_of.hpp>

using namespace std;
using namespace boost::assign;

const unsigned NonMartiale::Inexistant( 0xFF );

/**
 * Objet qui n'a pas de nom et un coût nul, utilisé comme un objet
 * statique.
 */
NonMartiale NonMartialeInconnue;

/**
 * Permet d'accéder à l'objet NonMartialeInconnue.
 *
 * @return une référence constante sur NonMartialeInconnue.
 */
const NonMartiale& nonMartialeInconnue()
{
  return NonMartialeInconnue;
}

/**
 * Constructeur standard, pour deux traits pouvant apporter un bonus
 * au score de compétence.
 *
 * @param[in] nom nom de la compétence
 * @param[in] prix coût de la compétence.
 * @param[in] base valeur de base de éa compétence.
 * @param[in] trait1 numéro du premier trait donnant un bonus.
 * @param[in] trait1 numéro du second trait donnant un bonus.
 * @param[in] cat catégorie de classe pouvant acheter la compétence.
 */
NonMartiale::NonMartiale( const std::string& nom, const unsigned& prix,
			  const unsigned& base, const unsigned& trait1,
			  const unsigned& trait2, const TypeClasse& cat )
  : ADDArticleObjet( "NonMartiale", nom, prix ),
    ValeurBase( base ), CategorieAdmise( cat )
{
  TraitBonus = list_of( trait1 )( trait2 );
}

/**
 * Constructeur standard, pour un trait pouvant apporter un bonus au
 * score de compétence.
 *
 * @param[in] nom nom de la compétence
 * @param[in] prix coût de la compétence.
 * @param[in] base valeur de base de éa compétence.
 * @param[in] trait numéro du trait donnant un bonus.
 * @param[in] cat catégorie de classe pouvant acheter la compétence.
 */
NonMartiale::NonMartiale( const std::string& nom, const unsigned& prix,
			  const unsigned& base, const unsigned& trait,
			  const TypeClasse& cat )
  : ADDArticleObjet( "NonMartiale", nom, prix ), ValeurBase( base ),
    CategorieAdmise( cat )
{
  TraitBonus = list_of( trait );
}

/**
 * Constructeur standard, sans trait pouvant apporter un bonus au
 * score de compétence.
 *
 * @param[in] nom nom de la compétence
 * @param[in] prix coût de la compétence.
 * @param[in] base valeur de base de éa compétence.
 * @param[in] cat catégorie de classe pouvant acheter la compétence.
 */
NonMartiale::NonMartiale( const std::string& nom, const unsigned& prix,
			  const unsigned& base, const TypeClasse& cat )
  : ADDArticleObjet( "NonMartiale", nom, prix ), ValeurBase( base ),
    CategorieAdmise( cat )
{}

/**
 * Constructeur de copie, qui permet de faire une copie sure d'une
 * instance.
 *
 * @param[in] nonMart instance de NonMartiale à copier.
 */
NonMartiale::NonMartiale( const NonMartiale& nonMart )
  : ADDArticleObjet( nonMart ),
    ValeurBase( nonMart.valeurBase() ),
    CategorieAdmise( nonMart.categorieAdmise() )
{
  TraitBonus.assign( nonMart.traitBonus().begin(), nonMart.traitBonus().end() );
}

/**
 * Le destructeur n'a rien de spécial à faire.
 */
NonMartiale::~NonMartiale()
{}

/**
 * Opérateur d'affectation, permettant de copier une instance dans une
 * autre.
 *
 * @param[in] nonMart instance de NonMartiale que l'on veut copier.
 */
const NonMartiale& NonMartiale::operator=( const NonMartiale& nonMart )
{
  Nom             = nonMart.nom();
  Prix            = nonMart.prix();
  ValeurBase      = nonMart.valeurBase();
  CategorieAdmise = nonMart.categorieAdmise();

  TraitBonus.assign( nonMart.traitBonus().begin(),
		     nonMart.traitBonus().end() );

  return *this;
}

ostream& operator<<( ostream& os, const NonMartiale& nonMart )
{
  os << nonMart.nom() << ", coût = " << nonMart.prix()
     << ", valeur de base = " << nonMart.valeurBase();

  if ( nonMart.nbrTraitBonus() > 0 )
    os << ", bonus donné par " << Caracteristique( nonMart.traitBonus( 0 ) );

  if ( nonMart.nbrTraitBonus() > 1 )
    os << " ou par " << Caracteristique( nonMart.traitBonus( 1 ) );

  return os;
}

FlotMessage& operator<<( FlotMessage& flot, const NonMartiale& nonMart )
{
  flot << nonMart.nom() << ", coût = " << nonMart.prix()
     << ", valeur de base = " << nonMart.valeurBase();

  if ( nonMart.nbrTraitBonus() > 0 )
    flot << ", bonus donné par " << Caracteristique( nonMart.traitBonus( 0 ) );

  if ( nonMart.nbrTraitBonus() > 1 )
    flot << " ou par " << Caracteristique( nonMart.traitBonus( 1 ) );

  return flot;
}

/**
 * Permet d'accéder à la valeur initiale de la compétence non
 * martiale.
 *
 * @return une référence constante sur ValeurBase.
 */
const unsigned& NonMartiale::valeurBase() const
{
  return ValeurBase;
}

/**
 * Permet de connaître le nombre de trait pouvant apporter un bonus à
 * la compétence non martiale (nombre pouvant varier entre 0 et 2).
 *
 * @return la taille du conteneur TraitBonus.
 */
unsigned NonMartiale::nbrTraitBonus() const
{
  return TraitBonus.size();
}

/**
 * Permet d'accéder au trait apportant un bonus voulu.
 *
 * @param[in] i indice du trait dans le conteneur TraitBonus;
 *
 * @return une référence constante sur le trait (pas sa valeur), ou
 * sur Inexistant si \c i est plus grand que la taille du conteneur.
 */
const unsigned& NonMartiale::traitBonus( const unsigned& i ) const
{
  return i >= TraitBonus.size() ? Inexistant : TraitBonus.at( i );
}

/**
 * Permet d'accéder au conteneur TraitBonus.
 *
 * @return une référence constante sur TraitBonus.
 */
const vector< unsigned >& NonMartiale::traitBonus() const
{
  return TraitBonus;
}

/**
 * Permet d'accéder à la catégorie de classe à laquelle la compétence
 * est destinée.
 *
 * @return une référence constante sur CategorieAdmise.
 */
const TypeClasse& NonMartiale::categorieAdmise() const
{
  return CategorieAdmise;
}
